package org.finesys.auth.configure;

import lombok.RequiredArgsConstructor;
import org.finesys.common.security.authentication.configurer.FormIdentityLoginConfigurer;
import org.finesys.common.security.authentication.handler.AuthSessionInfomationExpiredStrategy;
import org.finesys.common.security.authentication.password.DaoAuthenticationProvider;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
@EnableConfigurationProperties(SecurityPermitAllProperties.class)
@RequiredArgsConstructor
public class SecurityConfigure {

    //放行配置
    private final SecurityPermitAllProperties securityPermitAllProperties;

    /**
     * 默认安全策略过滤器链
     */
    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests(authorizeRequests ->

                        //放行配置
                        authorizeRequests.antMatchers(securityPermitAllProperties.getUrls()).permitAll()
                                //swagger
                                //其他路径都需要授权
                                .anyRequest().authenticated())
                // 避免iframe同源无法登录许iframe
                .headers().frameOptions().sameOrigin()
                //关闭csrf攻击防护
                .and().csrf().disable();
        //表单登录个性化
        new FormIdentityLoginConfigurer().init(httpSecurity);
        //会话处理
        httpSecurity.sessionManagement(session -> {
            session.maximumSessions(1).expiredSessionStrategy(new AuthSessionInfomationExpiredStrategy());//同一个账户只允许1个登录
        });
        //处理UsernamePasswordAuthenticationToken
        httpSecurity.authenticationProvider(new DaoAuthenticationProvider());
        return httpSecurity.build();
    }

    /**
     * 暴露静态资源
     */
    @Bean
    @Order(0)
    public SecurityFilterChain resources(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.requestMatchers(matchers -> matchers.antMatchers("/actuator/**", "/css/**", "/error"))
                .authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll())
                .requestCache().disable()
                .securityContext().disable()
                .sessionManagement().disable();
        return httpSecurity.build();
    }

}
